/*
The hdd.c file implements the low-level Hard Disk driver
*/


#include <globals.h>
#include <klib.h>
#include <linkedlist.h>

#include <dev.h>
#include <hdd.h>

//Private Includes
#include <vfs_info.h>
#include <mbr.h>
#include <fat32.h>

// for IDE_PRIMARY...
#include "../hdd/include/ide.h"


/* Data structures */
ptr_list_t partition_list=NULL;

/* Private functions prototypes */


void vfs_initialize(void);

/* Functions implementation */

void vfs_initialize(void)
  {
    struct dev_device *dev;
    struct vfs_partition_info *partition;
    ptr_iterator_t iter;

    int tmp_controller,tmp_disk,tmp_partition;


    printf("Initializing VFS...\n");

    // initialize partitions list
    partition_list=llist_make_list();

    // TO DO: get a list of hard disks...
    // for each hard disk, read its MBR
    // and populate this list

    // for now assume only first controller and first hard disk
    if (!hdd_detect(IDE_PRIMARY,0))
      {
	// Read its partitions and append them to the list
	vfs_mbr_initialize(0,0,partition_list);

	// Create a device for the hard disk
	dev=(struct dev_device *)malloc(sizeof(struct dev_device));

	dev->major = DEV_MAJOR_HDD_IDE;
	dev->minor = disk_to_minor(0,0,-1);   // -1 = whole disk

	sprintf(dev->name,"hd%d",0);
	dev->flags = DEV_FLG_BLOCK | DEV_FLG_READ | DEV_FLG_WRITE | DEV_FLG_META;
	dev->state = 0;
	dev->interface = NULL;
	dev->meta_info = NULL;
	dev->bus = NULL;

	// Notify the device manager about the new device
	dev_add_device(dev);
      }

    //vfs_mbr_diagnostics();

    //vfs_fat32_initialize();
    //vfs_fat32_diagnostics();


    // Make devices according to partitions found
    // get iterator on partitions
    iter=llist_get_nodes(partition_list);

    while (llist_iter_has_next(iter))
      {
        partition=(struct vfs_partition_info *)llist_iter_next(iter);
	dev=(struct dev_device *)malloc(sizeof(struct dev_device));

	dev->major = partition->major;
	dev->minor = partition->minor;

	minor_to_disk(partition->minor,&tmp_controller,&tmp_disk,&tmp_partition);
	tmp_disk = tmp_controller<<1 + tmp_disk;
	sprintf(dev->name,"hd%dp%d",tmp_disk,tmp_partition);
	dev->flags = DEV_FLG_BLOCK | DEV_FLG_READ | DEV_FLG_WRITE | DEV_FLG_META;
	dev->state = 0;
	dev->interface = NULL;
	dev->meta_info = NULL;
	dev->bus = NULL;

	// Notify the device manager about the new device
	dev_add_device(dev);	
      }

    free(iter);

    // Print device list...
    dev_print_list();
  }

/*
int vfs_fat32_mount(char *device, char *mount_point, int flags);
int vfs_fat32_unmount(char *device);
int vfs_fat32_open(int *fd, char *path, int mode);
int vfs_fat32_close(int *fd);
int vfs_fat32_create(char *path, int flags);
int vfs_fat32_delete(char *path);
int vfs_fat32_read(int fd, void *buf, size_t count);
int vfs_fat32_write(int fd, void *buf, size_t count);
int vfs_fat32_walk(int fd, char *path);
int vfs_fat32_meta_read(int fd, char *key, void *value, size_t count);
int vfs_fat32_meta_write(int fd, char *key, void *value, size_t count);
*/
